Skip to content

refactor: replace @voidzero-dev/vite-plus-test with upstream vitest@4.1.5#1588

Open
Brooooooklyn wants to merge 57 commits into
mainfrom
refactor/replace-vite-plus-test-with-vitest
Open

refactor: replace @voidzero-dev/vite-plus-test with upstream vitest@4.1.5#1588
Brooooooklyn wants to merge 57 commits into
mainfrom
refactor/replace-vite-plus-test-with-vitest

Conversation

@Brooooooklyn
Copy link
Copy Markdown
Member

@Brooooooklyn Brooooooklyn commented May 15, 2026

Summary

Deletes the bundled @voidzero-dev/vite-plus-test wrapper and consumes upstream vitest@4.1.5 (plus @vitest/browser*) directly. The vite redirection role that drove the wrapper is now handled cleanly by package-manager overrides (vite@voidzero-dev/vite-plus-core), so the bundle was dead weight that lagged upstream releases.

Public API contract preserved:

  • vite-plus/test* IS the public test API — existing user code (import { vi } from 'vite-plus/test', etc.) is NEVER rewritten.
  • New vite-plus users don't install vitest or @vitest/* separately; they come in transitively as direct deps of vite-plus.
  • vp migrate on an upstream-vitest project still forward-migrates vitest, vitest/*, @vitest/browser*, declare-module specifiers, and /// <reference types> directives to the vite-plus/test* surface (one-time transition).

Notable changes:

  • packages/cli/build.ts: syncTestPackageExports auto-generates ./test/* shims from upstream vitest's exports map, plus ./test/<provider> and ./test/browser/providers/<short> shims projected from each @vitest/browser-* package's exports.
  • packages/cli/package.json: adds @vitest/browser, @vitest/browser-playwright, @vitest/browser-preview, @vitest/browser-webdriverio as direct catalog deps pinned to 4.1.5.
  • crates/vite_global_cli/src/commands/version.rs: vitest ToolSpec points at the vitest package directly.
  • packages/cli/src/resolve-test.ts: resolves vitest/package.json and reads bin.vitest so vp test invokes upstream vitest.
  • packages/cli/src/utils/constants.ts: drops vitest from VITE_PLUS_OVERRIDE_PACKAGES; only vite remains a managed key.
  • packages/cli/src/migration/migrator.ts:
    • Adds an isVitestAdjacent flag that flips needVitePlus = true for projects with packages like vitest-browser-svelte even when there's no vite/oxlint/tsdown to migrate.
    • Adds pruneLegacyWrapperAliases / pruneYamlMapLegacyWrapperAliases sweeps that rewrite stale vitest: npm:@voidzero-dev/vite-plus-test@* aliases to ^4.1.5 (so existing catalog: refs keep resolving) and drop other stale wrapper-targeted keys.
  • packages/cli/src/migration/bin.ts: adds a handleInstallResult helper so failed reinstalls warn the user, append to report.warnings, and flip process.exitCode instead of being silently reported as success.

User-visible behavior changes

vp test -h and live test runs now show vitest's native banner (vitest/<semver>, RUN v<semver> <cwd>) instead of the wrapper-rebranded output (vp test/<semver>, RUN <cwd>). This is the tradeoff for delegating directly to upstream vitest without a wrapper layer.

Test plan

  • cargo test -p vite_migration --lib: 167 tests pass
  • pnpm exec vitest run (packages/cli): 374 tests pass
  • pnpm bootstrap-cli succeeds
  • pnpm -F vite-plus snap-test-global + snap-test-local: all fixtures regenerated; diffs only reflect expected behavior (forward import rewrites, @vitest/browser* removed from user devDeps, playwright/webdriverio preserved as peers, stale vite-plus-test catalog aliases normalized to ^4.1.5).
  • Manual end-to-end: vp test on a fixture using import { vi } from 'vite-plus/test'; vi.mock(...). See "Follow-up" below.
  • Manual end-to-end: vp migrate on a fresh upstream-vitest project.
  • pnpm install clean: zero @voidzero-dev/vite-plus-test references in the lockfile, browser-provider packages installed transitively via vite-plus.

Follow-up

@vitest/mocker hoists vi.mock(...) calls only when the import source is the literal string 'vitest' (@vitest/mocker@4.1.5/dist/chunk-hoistMocks.js hardcodes hoistedModule = "vitest"). User code that imports vi from 'vite-plus/test' won't get its mocks hoisted, which silently breaks mocking. The plan is to contribute upstream a hoistedModule?: string | string[] option to hoistMocks() so vite-plus can pass ['vitest', 'vite-plus/test']. Tracked as a separate effort — this PR ships the wrapper removal independently; the mocker fix can land later as a @vitest/mocker point release.

🤖 Generated with Claude Code


Note

Medium Risk
Touches CLI build/export generation and migration rewrite rules, plus CI packaging/overrides; mistakes could break vite-plus/test* resolution or ecosystem smoke tests across package managers (especially bun). No direct security impact.

Overview
Switches Vite+’s test surface from the bundled @voidzero-dev/vite-plus-test wrapper to direct upstream vitest + @vitest/browser* dependencies, while preserving the public vite-plus/test* import contract via regenerated shims and updated package.json exports.

Updates the migration/import rewriter to handle @vitest/browser* subpaths more precisely (including provider/context mappings) and to stop rewriting declare module 'vitest' / @vitest/* augmentations, plus expands file scanning to include .cjs/.cts.

Refactors CI/ecosystem workflows to stop packing/publishing the removed test package, pin packed tgz versions to 0.0.0, and add a bun-specific vite tgz alias workaround; also enhances the deps-upgrade script to bump vitest-related catalog entries, workflow pins, a VITEST_VERSION constant, and the @vitest/mocker pnpm patch key/file name in sync.

Reviewed by Cursor Bugbot for commit 2d88fd9. Bugbot is set up for automated code reviews on this repo. Configure here.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 15, 2026

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit 2d88fd9
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a0dca15d827ca0008f0b622

Comment thread packages/cli/src/migration/migrator.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 365a61de42

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/resolve-test.ts
Brooooooklyn added a commit that referenced this pull request May 15, 2026
…mat/typo

PR #1588 CI failures:
- Force-override mode (VP_FORCE_MIGRATE=1, set by test-vp-create.yml and
  ecosystem-ci) now re-pins any pre-existing vite-plus range to the local
  tgz path in monorepo workspace packages. Without this, pnpm reads the
  published vite-plus@0.1.21 metadata to resolve transitive deps including
  @voidzero-dev/vite-plus-test@0.1.21, which shadowed upstream vitest@4.1.5
  at runtime and broke vp create monorepo tests.
- typos CI: rename yarn-PnP to yarn Plug'n'Play (Pn→On false positive).
- vp check: format packages/cli/build.ts shim-generation block.
- Rename __dirname in install-failure-guard.spec.ts to satisfy
  eslint(no-underscore-dangle).
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4fafa67971

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/build.ts
Comment thread .github/scripts/upgrade-deps.ts
Comment thread packages/cli/src/migration/bin.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec69abaadb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/package.json
Comment thread packages/cli/src/migration/migrator.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 381b6e2c20

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/migration/migrator.ts Outdated
Comment thread packages/cli/build.ts
Brooooooklyn added a commit that referenced this pull request May 15, 2026
…mat/typo

PR #1588 CI failures:
- Force-override mode (VP_FORCE_MIGRATE=1, set by test-vp-create.yml and
  ecosystem-ci) now re-pins any pre-existing vite-plus range to the local
  tgz path in monorepo workspace packages. Without this, pnpm reads the
  published vite-plus@0.1.21 metadata to resolve transitive deps including
  @voidzero-dev/vite-plus-test@0.1.21, which shadowed upstream vitest@4.1.5
  at runtime and broke vp create monorepo tests.
- typos CI: rename yarn-PnP to yarn Plug'n'Play (Pn→On false positive).
- vp check: format packages/cli/build.ts shim-generation block.
- Rename __dirname in install-failure-guard.spec.ts to satisfy
  eslint(no-underscore-dangle).
@Brooooooklyn Brooooooklyn force-pushed the refactor/replace-vite-plus-test-with-vitest branch from 5c48da8 to 39efcbf Compare May 15, 2026 13:15
Comment thread packages/cli/src/migration/bin.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39efcbf239

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/vite_migration/src/import_rewriter.rs
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2fceee5296

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/resolve-test.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b888329d76

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/migration/migrator.ts
@Brooooooklyn
Copy link
Copy Markdown
Member Author

Upstream blockers (still needed after the fixes in this PR)

  • @vitest/mocker: the static hoister hardcodes hoistedModule = "vitest" so vi.mock() calls authored as import { vi } from 'vite-plus/test' are silently not hoisted — we ship a defineConfig-injected pre-stage Vite plugin (commit d69fe03) that rewrites 'vite-plus/test''vitest' at transform time as a workaround, but the long-term fix is exposing hoistedModule as a configurable option upstream.
  • rolldown/oxc parser: rejects the legal TypeScript syntax import type Default, { Named } from 'mod', breaking vp build against .d.ts files such as postcss@8.5.8's that use this form.

Comment thread .github/workflows/test-vp-create.yml Outdated
Comment thread ecosystem-ci/patch-project.ts Outdated
@Brooooooklyn
Copy link
Copy Markdown
Member Author

Upstream blockers (updated)

After the latest fixes (21937c5b1), the remaining upstream items are:

  • @vitest/mocker: hardcodes hoistedModule = "vitest" in its static hoister, so any redistributor that surfaces vi under a different specifier breaks vi.mock() silently — we now rewrite 'vite-plus/test''vitest' in the Rust migrator (commit 21937c5) plus keep a runtime Vite plugin (d69fe03) as a safety net, but the long-term fix is exposing hoistedModule as a configurable option upstream so vite-plus/test could also be recognized natively.
  • rolldown/oxc parser: rejects the legal TypeScript syntax import type Default, { Named } from 'mod', breaking vp build against .d.ts files such as postcss@8.5.8's that use this form (only vp-config E2E remains failing on this).

@Brooooooklyn
Copy link
Copy Markdown
Member Author

Final status (after b6b5b8b)

The aggressive Rust source-rewrite in 21937c5 (which made 'vitest' canonical) was reverted because it broke vp create templates that use from "vitest" and rely on the forward rewrite to resolve to vite-plus/test. The reverse-direction migration was over-reach and the cure was worse than the disease for the affected projects (vinext's 4 vi.mock files).

Confirmed upstream blockers:

  • @vitest/mocker: hardcodes hoistedModule = "vitest" in its static hoister, so any redistributor surfacing vi under a different specifier breaks vi.mock() silently — affects ~4 files in vinext that import vi from vite-plus/test (the runtime plugin in d69fe03 handles non-mocker vi usage but cannot intercept the static hoister which runs in vitest's own plugin pipeline). The long-term fix is exposing hoistedModule as a configurable option upstream.
  • rolldown/oxc parser: rejects the legal TypeScript syntax import type Default, { Named } from 'mod', breaking vp build against .d.ts files such as postcss@8.5.8's that use this form (only vp-config E2E remains failing on this).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6b5b8b0bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/index.ts
Comment thread .github/scripts/upgrade-deps.ts
Comment thread crates/vite_migration/src/import_rewriter.rs
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 60b7d0f0ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/index.ts
Comment thread packages/cli/src/utils/constants.ts Outdated
@Brooooooklyn
Copy link
Copy Markdown
Member Author

Final status — branch HEAD 3ffb7cd

E2E now at expected steady state. The two remaining upstream items:

  • @vitest/mocker hardcodes hoistedModule = "vitest" so the static mock hoister doesn't recognize vi imported via redistributor specifiers — needs upstream PR exposing hoistedModule as a configurable option. (Workaround in this PR: defineConfig injects a pre-stage Vite plugin that rewrites 'vite-plus/test''vitest', propagated into test.projects entries.)
  • rolldown/oxc parser rejects valid TypeScript import type Default, { Named } from 'mod' syntax — breaks vp build against postcss@8.5.8's .d.ts declarations (only vp-config E2E still fails on this).

Everything else (npmx.dev, vinext, vue-mini, frm-stack, varlet, vitepress, reactive-resume, rollipop, dify, etc.) is now green.

Brooooooklyn added a commit that referenced this pull request May 16, 2026
…mat/typo

PR #1588 CI failures:
- Force-override mode (VP_FORCE_MIGRATE=1, set by test-vp-create.yml and
  ecosystem-ci) now re-pins any pre-existing vite-plus range to the local
  tgz path in monorepo workspace packages. Without this, pnpm reads the
  published vite-plus@0.1.21 metadata to resolve transitive deps including
  @voidzero-dev/vite-plus-test@0.1.21, which shadowed upstream vitest@4.1.5
  at runtime and broke vp create monorepo tests.
- typos CI: rename yarn-PnP to yarn Plug'n'Play (Pn→On false positive).
- vp check: format packages/cli/build.ts shim-generation block.
- Rename __dirname in install-failure-guard.spec.ts to satisfy
  eslint(no-underscore-dangle).
@Brooooooklyn Brooooooklyn force-pushed the refactor/replace-vite-plus-test-with-vitest branch from 3ffb7cd to a0d248e Compare May 16, 2026 09:20
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0d248e65e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/define-config.ts Outdated
Comment thread packages/cli/src/migration/migrator.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a5b2697e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/define-config.ts
Comment thread .github/workflows/test-vp-create.yml Outdated
Brooooooklyn and others added 23 commits May 20, 2026 22:18
…l success

The initial install (pre-migration) is best-effort — migration
proceeds regardless of its outcome, and the final install (with
--force / --no-frozen-lockfile) is the authoritative recovery.
But `handleInstallResult` was being called on both summaries and
setting `process.exitCode` on either failure, so a successful
final install was being clobbered by a failed initial install's
exit code, making the migration look failed when it wasn't.

Add a `propagateExitCode` opt-out and apply it to the initial
call only. Both failures still get reported via `report.warnings`.
The env var replaces VITE_PLUS_OVERRIDE_PACKAGES entirely, so the
CI's previous map (which only listed vite + vite-plus-core) left
created projects with a catalog missing every vitest entry. Mirror
the vitest family from ecosystem-ci/patch-project.ts so installs
succeed.
- upgrade-deps.ts now bumps the @vitest/browser, @vitest/browser-playwright,
  @vitest/browser-preview, @vitest/browser-webdriverio catalog entries
  alongside the vitest line, and rewrites the VITEST_VERSION constant
  in packages/cli/src/utils/constants.ts.
- ecosystem-ci/patch-project.ts imports VITEST_VERSION from the CLI
  constants so the three places that previously hardcoded "4.1.5"
  collapse to a single source of truth (constants.ts).
…l imports

The previous regex-only rewriter ran on raw source text and would
mutate string content that happened to contain `from 'vite-plus/test'`
(template literals, error messages, fixtures). Switch the ESM
import/dynamic-import path to es-module-lexer so only actual import
specifiers get spliced. CJS `require()` keeps a tightened
boundary-anchored regex.

Added 4 unit tests covering the false-positive cases.
`LEGACY_WRAPPER_FALLBACK_VERSIONS.vitest` was set to `^${VITEST_VERSION}`,
while fresh migrations write the exact `VITEST_VERSION` via
`VITE_PLUS_OVERRIDE_PACKAGES`. Projects cleaned up from a stale
`@voidzero-dev/vite-plus-test` alias should land on the same exact
pin as fresh migrations, not a caret range that allows unintended
drift on reinstall.
The workflow's VP_OVERRIDE_PACKAGES JSON hardcodes the vitest
family at "4.1.5" ten times. Without rewriting this file on
bump, CI's vp create tests pin a stale vitest version after the
next daily upgrade. Add updateTestVpCreateWorkflow alongside
the constants.ts + pnpm-workspace.yaml rewrites.
es-module-lexer's `s`/`e` offsets bound the specifier name *without*
quotes for static imports but include the quotes (as part of the
expression) for dynamic imports. The previous splice replaced
specifier-plus-quotes with a bare `vitest`, producing
`import(vitest)` instead of `import('vitest')`. Branch on `d` to
wrap dynamic replacements in quotes.
The mocker's static hoister hardcodes `hoistedModule = "vitest"` and bails
on any other source, leaving `vi.mock(...)` un-hoisted and producing TDZ
errors at runtime (`Cannot access '__vi_import_0__' before initialization`).

After `vp migrate` rewrites `import { vi } from 'vitest'` to
`'vite-plus/test'`, the user's `vi.mock(...)` calls hit this path. Patch
the hoister to also recognize `'vite-plus/test'` so the public test API
works without forcing a runtime source rewrite.

To be replaced by an upstream PR that exposes `hoistedModule` as
`string | string[]`.
…/TSX

The vite-plus/test→vitest rewrite relied on es-module-lexer to scope
replacements to real import statements, but the lexer cannot parse JSX
syntax. For .tsx test files containing `import { vi } from 'vite-plus/test'`
plus JSX in the body, parse() threw, our silent catch left `imports`
undefined, and the source flowed through unchanged. Downstream
@vitest/mocker then bailed on the unknown specifier, dropped the
`vi.mock(...)` hoist, and crashed with
`Cannot access '__vi_import_0__' before initialization`.

Detect the throw and fall back to two tight regexes targeting
`from 'vite-plus/test'` and `import('vite-plus/test')`. The backreferenced
quote forbids subpath matches like `vite-plus/test/browser`, and both
contexts require statement-position keywords so string-literal noise is
left alone.

Add JSX/TSX coverage to the unit tests so this regression is locked down.
…kages

Three breaking changes carried over from the wrapper deletion are
addressed:

1. `./test/client`, `./test/locators`, `./test/matchers`, `./test/utils`,
   `./test/context` exports were dropped in the wrapper removal but
   `packages/cli/src/oxlint-plugin.ts:36-37` still autofixes
   `@vitest/browser/client` and `@vitest/browser/locators` to those
   exact paths. Without the exports, `vp lint --fix` produced
   unresolvable imports. Restore them as shims projecting the matching
   `@vitest/browser/<sub>` subpaths.

2. `./test/browser-compat` is restored as a shim re-exporting
   `asLocator`, `defineBrowserCommand`, `defineBrowserProvider`,
   `parseKeyDef`, `resolveScreenshotPath` from `@vitest/browser`. The
   path is used by downstream consumers that point `@vitest/browser` at
   vite-plus via a package-manager override; restoring it preserves the
   wrapper-era surface.

3. `@testing-library/jest-dom`, `@storybook/test`, and `jest-extended`
   are auto-merged into `test.server.deps.inline` (root + per-project)
   so `expect.extend()` matcher registrations land on the same `expect`
   instance the test runtime uses. The previous wrapper applied this as
   a build-time patch to vitest's CLI chunk (vitest issue #897); the
   wrapper-free architecture re-applies it inside `defineConfig`.

The auto-inline merge is idempotent, respects `inline: true` opt-in,
deduplicates string entries, and recognises regexp entries that already
match an auto-inline package.
`packages/cli/src/index.ts` deliberately uses a curated re-export from
`vitest/config` that omits `mergeConfig` to avoid colliding with the
`mergeConfig` re-exported from `@voidzero-dev/vite-plus-core`. The CJS
entry still spread the full `vitest/config` namespace, so CJS consumers
ended up with vitest's `mergeConfig` (which delegates to upstream `vite`)
instead of vite-plus-core's. ESM and CJS now expose the same identifiers.
- Drop `?? {}` spread fallbacks (unicorn/no-useless-fallback-in-spread):
  optional chaining already guards the spread, the fallback is dead.
- Wrap single-statement `continue` in braces (eslint/curly).

No behavior change.
The previous regex fallback (`/from\s+['"]vite-plus\/test['"]/g`) ran on
raw source when `es-module-lexer` threw on JSX/TSX, so it could mutate
the same substring inside string literals or JSX text. Switched to
`oxc-parser` which understands TSX and exposes precise specifier offsets
for static imports, dynamic imports, and `export … from` re-exports —
all three are needed because the fast-path lexer reports them in one
list while oxc separates them into staticImports / dynamicImports /
staticExports.
Consolidates the @emnapi/core 1.9.2 / 1.10.0 split that the oxc-parser
install introduced, so `pnpm dedupe --check` passes in CI.
…ojects

Browser-mode tests failed in established vite-plus projects (those that
depend only on `vite-plus`, with `vitest`/`@vitest/browser` transitive).
pnpm's isolated layout only exposes a package's direct deps, so the
browser-mode Vite dev server — rooted at the consumer project — could not
resolve `vitest/internal/browser` and the `@vitest/*` family, crashing
with "Failed to resolve import vitest/internal/browser".

Adds `vite-plus:vitest-resolver`, an enforce:'pre' resolveId plugin
injected alongside the specifier-rewrite plugin. It is a pure fallback:
it defers to the default resolver first (skipSelf) so projects that
already resolve fine see zero change, and only when that returns null
does it resolve from vite-plus's own dependency tree — `vitest` /
`@vitest/browser*` via a require anchored at this module, and the nested
`@vitest/*` family (deps of vitest) via a require anchored at vitest.
Bumps the `vitest` / `@vitest/browser*` catalog pins, the `VITEST_VERSION`
constant (which drives migration-injected overrides), and the
`VP_OVERRIDE_PACKAGES` workflow env from 4.1.5 to the latest stable 4.1.7.
The `@vitest/mocker` hoist patch is renamed to track the new version and
still applies cleanly (the patched context is unchanged in 4.1.7).
… exports

The blanket `@vitest/` → `vite-plus/test/` swap produced targets that
do not exist in the `vite-plus` package `exports` map, so migrated code
failed at runtime with ERR_PACKAGE_PATH_NOT_EXPORTED:

- `@vitest/browser/{client,locators,matchers,utils}` mapped to
  `vite-plus/test/browser/*` (only the bare `./test/*` keys exist).
- `@vitest/browser-<provider>/provider` mapped to
  `vite-plus/test/browser-<provider>/provider` (no such export).

Replace the single naive ast-grep rule with 12 mutually-exclusive
enumerated rules and split the triple-slash reference regex into five,
so `vp migrate` produces the same canonical targets as the
`oxlint-plugin.ts` autofix. Add the missing `matchers`/`utils` entries
to `oxlint-plugin.ts` so both implementations stay in sync.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The tgz-based create/e2e workflows reference fixed `*-0.0.0.tgz`
filenames (`repack-vite-tgz` input, `VP_VERSION`, `install-global-cli`,
`VP_OVERRIDE_PACKAGES`). A release commit bumped `packages/core` and
`packages/cli` to a published version, so `pnpm pack` emitted
`*-0.1.22.tgz` and the `Build vite-plus packages` job failed with
ENOENT on `voidzero-dev-vite-plus-core-0.0.0.tgz`.

Pin both packages to 0.0.0 with `pnpm pkg set` right before packing so
the emitted tgz names stay stable regardless of the committed version.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`replaceInstalledCheckoutPackages` symlinked `node_modules/vitest` and
`node_modules/@voidzero-dev/vite-plus-test` to `packages/test`, which
this branch deletes. The entries are never matched by the current snap
suite (only `create-framework-shim-vue` sets `linkCheckoutPackages` and
it installs neither package), but a future global snap test that does
install vitest would `rmSync` the real package and symlink it to the
now-missing `packages/test`. Remove both stale entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`pnpm pkg set` is not implemented (ERR_PNPM_NOT_IMPLEMENTED); pnpm
points to the npm CLI for `pkg` operations. Switch the version pin in
the tgz pack steps to `npm pkg set version=0.0.0`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The ecosystem-ci pack step pins packages/cli to 0.0.0 before packing, so
the installed local build reports 0.0.0. verify-install.ts still compared
against the committed packages/cli/package.json version (0.1.22 after the
release bump), failing every ecosystem E2E project with
"expected version 0.1.22, got 0.0.0". Pin the expected version to 0.0.0,
matching the fixed `vite-plus-0.0.0.tgz` that patch-project.ts references.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`externalDtsTypeOnlyPlugin` blindly prepended `import type ` to every
import line in postcss/lightningcss `.d.ts` files. For the
`import D, { N } from 'x'` shape that produced `import type D, { N }`,
which is invalid — a type-only import statement cannot mix a default
binding with named bindings. The dts bundler then failed with
`[PARSE_ERROR]` (surfaced by the `vp-config` ecosystem-ci project,
whose dependency graph routes postcss's `.d.ts` through this plugin).

Fold the default binding into the named clause as `{ default as D, N }`
before the generic prepend, in both the internal-file and
consumer-file branches.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Brooooooklyn Brooooooklyn force-pushed the refactor/replace-vite-plus-test-with-vitest branch from baca45e to 9b451f4 Compare May 20, 2026 14:19
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b451f4534

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pnpm-workspace.yaml
Brooooooklyn and others added 2 commits May 20, 2026 22:36
`vp pack --dts` inlined postcss's `.d.ts` into the declaration bundle
and failed with 61 MISSING_EXPORT errors for postcss type names.
postcss exposes its public types via `declare namespace postcss {
export {...} }` + `export = postcss` — a CJS namespace shape the dts
bundler cannot map named imports onto.

`externalDtsTypeOnlyPlugin` previously rewrote postcss/lightningcss
imports to type-only via regex, which neither parsed reliably for
default+named imports nor addressed the `export =` mismatch. Replace
it with a `resolveId` hook that marks postcss/lightningcss external
whenever imported from a `.d.ts` file, so emitted declarations keep
`import type { X } from 'postcss'` instead of inlining postcss's
`.d.ts` — standard dts-bundler treatment of third-party packages.
Runtime bundling is unaffected (the hook only fires for
declaration-file importers).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The daily upgrade script bumped the vitest catalog, VITEST_VERSION, and
the test-vp-create.yml pins, but never touched the @vitest/mocker entry
in patchedDependencies. pnpm keys patchedDependencies by exact version
and fails ERR_PNPM_PATCHED_PKG_DOES_NOT_MATCH on drift, so each vitest
bump broke the auto-upgrade PR. Rewrite the key + patch path and rename
the version-suffixed patch file as part of the upgrade run.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9513a3baa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +193 to +196
pattern: $STR
kind: string
regex: ^['"]@vitest/browser/(client|locators|matchers|utils)['"]$
inside:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rewrite @vitest/browser/providers imports during migration

This rule now rewrites only @vitest/browser/{client|locators|matchers|utils}, so valid imports like @vitest/browser/providers/playwright are left unchanged; in the same migration flow @vitest/browser is removed from dependencies (REMOVE_PACKAGES in packages/cli/src/migration/migrator.ts), which makes those unchanged imports unresolved after migration. Please add an import rewrite for @vitest/browser/providers/<name> to vite-plus/test/browser/providers/<name> to keep migrated projects working.

Useful? React with 👍 / 👎.

`vitest@4.1.7`'s dist/index.d.ts re-exports `ExpectPollOptions` from
`@vitest/expect`, which does not export that name. tsc tolerates the
dangling re-export (lazy resolution) but the rolldown dts bundler
resolves every re-export eagerly while inlining, so `vp pack --dts`
fails with MISSING_EXPORT. Extend externalDtsTypeOnlyPlugin to keep
vitest and @vitest/* external for .d.ts importers, the same treatment
already applied to postcss/lightningcss.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d88fd926b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

rule:
pattern: $STR
kind: string
regex: ^['"]@vitest/browser/(client|locators|matchers|utils)['"]$
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Rewrite @vitest/browser/providers imports during migration

The vitest import rules only rewrite @vitest/browser/(client|locators|matchers|utils) and omit @vitest/browser/providers/<name>, so migrations can leave imports like @vitest/browser/providers/playwright unchanged. In the same migration flow, @vitest/browser is removed from dependencies (packages/cli/src/migration/migrator.ts REMOVE_PACKAGES), which makes those unchanged provider imports unresolved after migration and breaks browser-mode configs/tests that use provider entrypoints.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant